/*
 * Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
 *
 * Licensed under the Mulan PSL v2.
 * You can use this file according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of the License at
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
 * FOR MORE DETAILS.
 */

#pragma once

#include <typeinfo>
#include <unordered_map>
#include <utility>

#include "DBManager/IRepository/Base/ISetRepository.h"
#include "DBManager/Repository/HDF5/Base/CacheRepositoryBase.h"

SG_DBMANAGER_HDF5_NAMESPACE_OPEN

template <typename T>
class DBManager_DECLSPEC SetRepositoryBase : public CacheRepositoryBase<T>, public virtual ISetRepository<T>
{
  public:
    explicit SetRepositoryBase (HDF5Database& database) : CacheRepositoryBase<T> (database) {};

    virtual ~SetRepositoryBase () = default;

    using CacheRepositoryBase<T>::Sort;
    using CacheRepositoryBase<T>::GetDataset;
    using CacheRepositoryBase<T>::GetDatasetInfo;
    using CacheRepositoryBase<T>::GetDatabase;
    using CacheRepositoryBase<T>::GetMainDatasetInfo;
    using CacheRepositoryBase<T>::GetIndexDatasetInfo;
    using CacheRepositoryBase<T>::DATASET;
    using CacheRepositoryBase<T>::GetIndexCache;

    /**
     * @brief 获取表单的行数（数据总量）。
     *
     * @return 表单的行数。
     */
    std::size_t Size () override
    {
        if (!this->GetMainCache ().m_writeStorage.empty ())
        {
            this->DumpWriteCahce ();
        }

        ///< 返回主表的行数
        return GetMainDatasetInfo ().GetRowCount ();
    }

    /**
     * @brief 获取所有的 ID。
     *
     * @return 包含所有 ID 的向量。
     */
    std::vector<SG::DataStructure::Common::Id> GetAllId ()
    {
        ///< 确保数据已排序
        Sort ();

        std::vector<SG::DataStructure::Common::Id> idList;
        if (this->GetMainDatasetInfo ().IsCreate ())
        {
            GetDataset (GetIndexDatasetInfo ()).read (idList);  ///< 读取所有 ID
        }

        return idList;
    }

    /**
     * @brief 计算指定 ID 的出现次数。
     *
     * @param id 要计算的 ID。
     * @return ID 出现的次数。
     */
    std::size_t Count (SG::DataStructure::Common::Id id) override
    {
        Sort ();

        auto allId = GetAllId ();  ///< 获取所有 ID

        auto range = std::equal_range (allId.begin (), allId.end (), id);

        return std::distance (range.first, range.second);
    }

    /**
     * @brief 向缓存中添加多个实体。当缓存达到最大数量时，将调用 `Dump()` 方法进行处理。
     *
     * @param entity 要添加的实体。
     */
    SG::DataStructure::Common::Status Add (std::vector<T>& entity) override
    {
        auto& mainCache = this->GetMainCache ();

        mainCache.m_writeStorage.insert (mainCache.m_writeStorage.end (), entity.begin (), entity.end ());

        // 如果缓存已满，则执行 Dump 操作
        if (mainCache.m_writeStorage.size () >= mainCache.m_limitSize)
        {
            this->DumpWriteCahce ();
        }

        GetMainDatasetInfo ().SetIsSequential (false);

        return SG::DataStructure::Common::Status::STATUS_Success;
    }

    /**
     * @brief 向缓存中添加一个实体。当缓存达到最大数量时，将调用 `Dump()` 方法进行处理。
     *
     * @param entity 要添加的实体。
     */
    SG::DataStructure::Common::Status Add (T& entity) override
    {
        auto& mainCache = this->GetMainCache ();

        mainCache.m_writeStorage.push_back (entity);  ///< 将实体添加到写缓存中

        // 如果缓存已满，则执行 Dump 操作
        if (mainCache.m_writeStorage.size () == mainCache.m_limitSize)
        {
            this->DumpWriteCahce ();
        }

        // 数据添加后对数据的处理
        this->AfterAdd (entity);

        GetMainDatasetInfo ().SetIsSequential (false);

        return SG::DataStructure::Common::Status::STATUS_Success;
    }

    /**
     * @brief 根据索引查找实体。
     *
     * @param index 要查找的索引。
     * @param _OUT entity 查找到的实体将存储在此参数中。
     * @return 如果索引有效且实体成功加载，则返回 `true`；否则返回 `false`。
     *
     * @throw std::runtime_error 如果索引超出范围。
     */
    SG::DataStructure::Common::Status FindByIndex (std::size_t index, T& _OUT entity) override
    {
        Sort ();

        // 检查索引是否超出范围
        if (GetMainDatasetInfo ().GetRowCount () <= index)
        {
            return SG::DataStructure::Common::Status::STATUS_Failure;
        }

        auto& mainCache = this->GetMainCache ();

        std::vector<T>* cacheVec;

        if (index >= mainCache.dataMaxIndex || index < mainCache.dataMinIndex || mainCache.dataMinIndex == 0)
        {
            cacheVec = this->LoadReadCache (index);
        }
        else
        {
            cacheVec = this->m_cacheHelper.template GetVectorFast<T> (mainCache.m_readCacheKey);
        }

        entity = cacheVec->at (index - mainCache.dataMinIndex);  ///< 获取实体

        return SG::DataStructure::Common::Status::STATUS_Success;
    }

    virtual void Sort ()
    {
        auto& mainInfo = this->GetMainDatasetInfo ();

        // 如果已有的数据未排序
        if (!mainInfo.IsSequential ())
        {
            auto& mainCache = this->GetMainCache ();

            // 将写的数据先dump
            if (!mainCache.m_writeStorage.empty ())
            {
                this->DumpWriteCahce ();
            }

            if (mainInfo.IsCreate ())
            {
                this->SortData ();
            }

            mainInfo.SetIsSequential (true);

            // 清除当前的读取缓存键和索引信息
            if (!mainCache.m_readCacheKey.empty ())
            {
                this->GetDatabase ().GetCachePool ().Remove (mainCache.m_readCacheKey);
            }

            mainCache.dataMinIndex = 0;
            mainCache.dataMaxIndex = 0;

            const std::string rangeCacheKey = mainInfo.GetPath () + std::string ("_SIdRangeCache");
            const std::string cacheKeyBase  = mainInfo.GetPath () + std::string ("_SIdRangeDataCache_");
            this->GetDatabase ().GetCachePool ().Remove (rangeCacheKey);
            this->GetDatabase ().GetCachePool ().Remove (cacheKeyBase);
        }
    }

    /**
     * @brief   : 根据SID查询原生数据
     * @tparam IT
     * @param   : sId
     * @param   : mainDatas
     * @return  :
     */
    template <typename IT>
    SG::DataStructure::Common::Status FindMainRangeBySId (SG::DataStructure::Common::Id sId, std::vector<IT>& _OUT mainDatas)
    {
        // 确保索引顺序正确
        Sort ();

        auto& mainInfo = this->GetMainDatasetInfo ();

        if (!mainInfo.IsCreate ())
        {
            return SG::DataStructure::Common::Status::STATUS_Failure;
        }

        auto& idxInfo = this->GetIndexDatasetInfo ();

        // 1) 尝试从缓存获取 SID -> (start,length) 的范围映射
        const std::string rangeCacheKey = mainInfo.GetPath () + std::string ("_SIdRangeCache");

        using RangePair = std::pair<std::size_t, std::size_t>;

        auto* rangeCache = this->m_cacheHelper.template GetUnorderedMapFast<SG::DataStructure::Common::Id, RangePair> (rangeCacheKey);

        if (rangeCache == nullptr)
        {
            // 未命中缓存：读取完整索引表，构建所有 SID 的范围缓存
            std::vector<SG::DataStructure::Common::Id> idList;
            this->GetDataset (idxInfo).read (idList);

            // 统计唯一 SID 数量（idList 已排序），避免过度预分配
            std::size_t uniqueCount = 0;
            {
                std::size_t j = 0;
                while (j < idList.size ())
                {
                    ++uniqueCount;
                    const auto& v = idList[j];
                    while (j < idList.size () && !(idList[j] < v) && !(v < idList[j]))
                    {
                        ++j;
                    }
                }
            }

            auto* newMap = new std::unordered_map<SG::DataStructure::Common::Id, RangePair> ();
            newMap->reserve (uniqueCount);

            std::size_t i = 0;
            while (i < idList.size ())
            {
                const auto&       curId = idList[i];
                const std::size_t st    = i;
                while (i < idList.size () && !(idList[i] < curId) && !(curId < idList[i]))
                {
                    ++i;
                }
                const std::size_t len = i - st;
                (*newMap)[curId]      = { st, len };
            }

            this->m_cacheHelper.template CacheUnorderedMap<SG::DataStructure::Common::Id, RangePair> (rangeCacheKey, newMap);
            rangeCache = newMap;
        }

        // 2) 根据 sId 查找范围
        auto it = rangeCache->find (sId);
        if (it == rangeCache->end ())
        {
            return SG::DataStructure::Common::Status::STATUS_Failure;
        }

        const std::size_t startIndex = it->second.first;
        const std::size_t length     = it->second.second;
        if (length == 0)
        {
            return SG::DataStructure::Common::Status::STATUS_Failure;
        }

        const std::size_t endIndex = startIndex + length;

        const std::string cacheKeyBase = mainInfo.GetPath () + std::string ("_SIdRangeDataCache_");
        const std::string dataCacheKey = cacheKeyBase;
        const std::string metaCacheKey = "Meta";

        auto* dataCache = this->m_cacheHelper.template GetVectorFast<IT> (dataCacheKey);
        auto* metaCache =
            this->m_cacheHelper.template GetFast<std::unordered_map<std::string, std::pair<std::size_t, std::size_t>>> (metaCacheKey);

        auto cacheCoversRange = [&] () -> bool {
            if (dataCache == nullptr || metaCache == nullptr || metaCache->find (dataCacheKey) == metaCache->end ())
            {
                return false;
            }
            auto& m = (*metaCache)[dataCacheKey];
            if (m.second <= m.first)
            {
                return false;
            }
            return startIndex >= m.first && endIndex <= m.second;
        };

        if (!cacheCoversRange ())
        {
            std::size_t cacheBegin  = 0;
            std::size_t cacheLength = 0;
            mainInfo.CalcIndexBeginAndLength (startIndex, _OUT cacheBegin, _OUT cacheLength, this->GetDatasetCacheSize ());

            if (cacheBegin + cacheLength < endIndex)
            {
                cacheLength                = endIndex - cacheBegin;
                const std::size_t rowCount = mainInfo.GetRowCount ();
                if (cacheBegin + cacheLength > rowCount)
                {
                    cacheLength = rowCount > cacheBegin ? rowCount - cacheBegin : 0;
                }
            }

            if (dataCache == nullptr)
            {
                dataCache = new std::vector<IT>;
                dataCache->reserve (cacheLength);
                this->m_cacheHelper.template CacheVector<IT> (dataCacheKey, dataCache);
            }
            else
            {
                dataCache->clear ();
                dataCache->reserve (cacheLength);
            }

            if (cacheLength > 0)
            {
                this->GetDataset (mainInfo).select ({ cacheBegin }, { cacheLength }).read (*dataCache);
            }
            else
            {
                dataCache->clear ();
            }

            if (metaCache == nullptr)
            {
                metaCache = new std::unordered_map<std::string, std::pair<std::size_t, std::size_t>> ();
                // 永久有效吧 因为全局只有一个
                this->m_cacheHelper.template CacheUnorderedMap<std::string, std::pair<std::size_t, std::size_t>> (
                    metaCacheKey, metaCache, 0);
            }

            (*metaCache)[dataCacheKey] = std::pair<std::size_t, std::size_t> (cacheBegin, cacheBegin + dataCache->size ());
        }

        if (!cacheCoversRange ())
        {
            mainDatas.clear ();
            mainDatas.reserve (length);
            this->GetDataset (mainInfo).select ({ startIndex }, { length }).read (mainDatas);
            return SG::DataStructure::Common::Status::STATUS_Success;
        }

        const std::size_t offset = startIndex - (*metaCache)[dataCacheKey].first;
        mainDatas.assign (dataCache->begin () + offset, dataCache->begin () + offset + length);

        return SG::DataStructure::Common::Status::STATUS_Success;
    }
};

SG_DBMANAGER_HDF5_NAMESPACE_CLOSE
